home *** CD-ROM | disk | FTP | other *** search
/ MacHack 2000 / MacHack 2000.toast / pc / The Hacks / MacHacksBug / Python 1.5.2c1 / Extensions / Imaging / PIL / ImageFile.py < prev    next >
Encoding:
Python Source  |  2000-06-23  |  5.2 KB  |  227 lines

  1. #
  2. # The Python Imaging Library.
  3. # $Id: ImageFile.py,v 1.1.1.2 1999/01/13 09:40:13 sjoerd Exp $
  4. #
  5. # base class for image file handlers
  6. #
  7. # history:
  8. # 95-09-09 fl    Created
  9. # 96-03-11 fl    Fixed load mechanism.
  10. # 96-04-15 fl    Added pcx/xbm decoders.
  11. # 96-04-30 fl    Added encoders.
  12. # 96-12-14 fl    Added load helpers
  13. # 97-01-11 fl    Use encode_to_file where possible
  14. # 97-08-27 fl    Flush output in _save
  15. # 98-03-05 fl    Use memory mapping where possible
  16. #
  17. # Copyright (c) Secret Labs AB 1997-98.
  18. # Copyright (c) Fredrik Lundh 1995-97.
  19. #
  20. # See the README file for information on usage and redistribution.
  21. #
  22.  
  23.  
  24. import Image
  25. import traceback, sys
  26.  
  27. MAXBLOCK = 65536
  28.  
  29. #
  30. # --------------------------------------------------------------------
  31. # Helpers
  32.  
  33. def _tilesort(t1, t2):
  34.     # sort on offset
  35.     return cmp(t1[2], t2[2])
  36.  
  37. #
  38. # --------------------------------------------------------------------
  39. # ImageFile base class
  40.  
  41. class ImageFile(Image.Image):
  42.     "Base class for image file format handlers."
  43.  
  44.     def __init__(self, fp = None, filename = None):
  45.  
  46.     self.im = None
  47.     self.mode = ""
  48.     self.size = (0, 0)
  49.     self.palette = None
  50.     self.tile = None
  51.     self.info = {}
  52.  
  53.     self.decoderconfig = ()
  54.     self.decodermaxblock = MAXBLOCK
  55.  
  56.         if type(fp) == type(""):
  57.         self.fp = open(fp, "rb")
  58.         self.filename = fp
  59.     else:
  60.         self.fp = fp
  61.         self.filename = filename
  62.  
  63.     try:
  64.         self._open()
  65.     except IndexError, v: # end of data
  66.         if Image.DEBUG > 1:
  67.         traceback.print_exc()
  68.         raise SyntaxError, v
  69.     except TypeError, v: # end of data (ord)
  70.         if Image.DEBUG > 1:
  71.         traceback.print_exc()
  72.         raise SyntaxError, v
  73.     except KeyError, v: # unsupported mode
  74.         if Image.DEBUG > 1:
  75.         traceback.print_exc()
  76.         raise SyntaxError, v
  77.  
  78.     if not self.mode or self.size[0] <= 0:
  79.         raise SyntaxError, "not identified by this driver"
  80.  
  81.     def draft(self, mode, size):
  82.     "Set draft mode"
  83.  
  84.     pass
  85.  
  86.     def verify(self):
  87.     "Check file integrity"
  88.  
  89.     # raise exception if something's wrong.  must be called
  90.     # directly after open, and closes file when finished.
  91.     self.fp = None
  92.  
  93.     def load(self, modify=0):
  94.     "Load image data based on tile list"
  95.  
  96.     Image.Image.load(self, modify)
  97.  
  98.     if self.tile is None:
  99.         raise IOError, "cannot load this image"
  100.     if not self.tile:
  101.         return
  102.  
  103.     self.map = None
  104.  
  105.     if self.filename and len(self.tile) == 1:
  106.         # try memory mapping
  107.         d, e, o, a = self.tile[0]
  108.         if d == "raw" and a[0] in ("L", "P", "RGBX", "RGBA", "CMYK"):
  109.         # FIXME: add support for "I;16"
  110.         try:
  111.             self.map = Image.core.map(self.filename)
  112.             self.map.seek(o)
  113.             self.im = self.map.readimage(
  114.             self.mode, self.size, a[1], a[2]
  115.             )
  116.         except (AttributeError, IOError):
  117.             self.map = None
  118.  
  119.     # create image memory if necessary
  120.     if not self.im or\
  121.        self.im.mode != self.mode or self.im.size != self.size:
  122.         self.im = Image.core.new(self.mode, self.size)
  123.  
  124.     # create palette (optional)
  125.         if self.mode == "P":
  126.             Image.Image.load(self, modify)
  127.  
  128.     if not self.map:
  129.  
  130.         # process tiles in file order
  131.         self.tile.sort(_tilesort)
  132.  
  133.         for d, e, o, a in self.tile:
  134.         d = Image._getdecoder(self.mode, d, a, self.decoderconfig)
  135.         self.load_seek(o)
  136.         try:
  137.             d.setimage(self.im, e)
  138.         except ValueError:
  139.             continue
  140.         try:
  141.             # FIXME: This is a hack to handle TIFF's JpegTables tag.
  142.             b = self.tile_prefix
  143.         except AttributeError:
  144.             b = ""
  145.         t = len(b)
  146.         while 1:
  147.             s = self.load_read(self.decodermaxblock)
  148.             if not s:
  149.             self.tile = []
  150.             raise IOError, "image file is truncated, %d bytes left" % len(b)
  151.             b = b + s
  152.             n, e = d.decode(b)
  153.             if n < 0:
  154.             break
  155.             b = b[n:]
  156.             t = t + n
  157.  
  158.     self.tile = []
  159.     self.fp = None # might be shared
  160.  
  161.     if not self.map and e < 0:
  162.         raise IOError, "decoder error %d when reading image file" % e
  163.  
  164.     # post processing
  165.     if hasattr(self, "tile_post_rotate"):
  166.         # FIXME: This is a hack to handle rotated PCD's
  167.         self.im = self.im.rotate(self.tile_post_rotate)
  168.         self.size = self.im.size
  169.  
  170.     self.load_end()
  171.  
  172.     def load_end(self):
  173.     # may be overridden
  174.     pass
  175.  
  176.     def load_seek(self, pos):
  177.     # may be overridden for contained formats
  178.     self.fp.seek(pos)
  179.  
  180.     def load_read(self, bytes):
  181.     # may be overridden for blocked formats (e.g. PNG)
  182.     return self.fp.read(bytes)
  183.  
  184.  
  185. #
  186. # --------------------------------------------------------------------
  187. # Save image body
  188.  
  189. def _save(im, fp, tile):
  190.     "Helper to save image based on tile list"
  191.  
  192.     im.load()
  193.     if not hasattr(im, "encoderconfig"):
  194.     im.encoderconfig = ()
  195.     tile.sort(_tilesort)
  196.     bufsize = max(MAXBLOCK, im.size[0] * 4) # see RawEncode.c
  197.     try:
  198.     fh = fp.fileno()
  199.     fp.flush()
  200.     except AttributeError:
  201.     # compress to Python file-compatible object
  202.     for e, b, o, a in tile:
  203.         e = Image._getencoder(im.mode, e, a, im.encoderconfig)
  204.         if o > 0:
  205.         fp.seek(o, 0)
  206.         e.setimage(im.im, b)
  207.         while 1:
  208.         l, s, d = e.encode(bufsize)
  209.         fp.write(d)
  210.         if s:
  211.             break
  212.         if s < 0:
  213.         raise IOError, "encoder error %d when writing image file" % s
  214.     else:
  215.     # slight speedup: compress to real file object
  216.     for e, b, o, a in tile:
  217.         e = Image._getencoder(im.mode, e, a, im.encoderconfig)
  218.         if o > 0:
  219.         fp.seek(o, 0)
  220.         e.setimage(im.im, b)
  221.         s = e.encode_to_file(fh, bufsize)
  222.         if s < 0:
  223.         raise IOError, "encoder error %d when writing image file" % s
  224.     try:
  225.         fp.flush()
  226.     except: pass
  227.